Arrays & Classes Quick Start Compile step once always make -k baseball8 mkdir labs cd labs Execute step mkdir 8 java Baseball8 cd 8 cp /samples/csc/156/labs/8/*. Submit step emacs Player.java & submit csc156abc 8 emacs Baseball8.java & Problem Statement and Specifications This is an exercise that will allow us to demonstrate the use of arrays where each array element is an instance of a user-defined class. This model can be thought of as the means of emulating a rudimentary data base, however the linear nature of an array would make such storage strategies difficult with large amounts of data. The input for this program is a sequential file that contains data for a baseball team where a sequence of lines in the file corresponds to the sequence of records in the array. Each line of the file contains four int values. The first of these int values is to be interpreted as a team player s number. Then comes that player s number of hits, that player s number of walks and that player s number of outs from a game on the team schedule. There is a unique number for each player, but there may be more than one line in the input file that has the same player number. This is to be interpreted as the player with that number having played in multiple games. Consequently, the order of the Player numbers can be random in the file. All output should be displayed on the monitor and should consist of each player s Number on the team followed by the accumulation of Hits, Walks and Outs that were stored in the input file under that player s number. Assignment 8 Statement: Write a program in a file named Baseball8.java that uses a Player class stored within an array. The program should read data from the file baseball.txt for input. The Player class is stored in a file named Player.java and supports a constructor that sets the four data attributes (Number, Hits, Walks and Outs) equal to zero. In addition, there are extractor and mutator methods for each of the data attributes. Finally, there is an overload of the method tostring() that provides support to display the data for each Player in a formatted manner using the System.out.print(), System.out.printf() or System.out.println() methods. After connecting to the input file baseball.txt, the array elements should be instantiated under the assumption that the team will contain no more than 20 Players. Then, for each line of data within baseball.txt, the program should input the Player team Number, the number of Hits, the number of Walks and the number of Outs for that particular game and use the Player methods to update the attribute fields for that 1
Player with that team Number. Your program will need to implement a sequential search for each Player team Number to determine if that Player already has data stored within the array or not. Upon reading all of the data from the file, the program should display each Player team Number, and the total number of Hits, the total number of Walks and the total number of Outs that were stored on the input lines of the file. Your Player class is already available for you using the files makefile and Player.java. Your main() method will need 2 methods, one for the sequential search of the array and another for the display of the array. 1/2 lab extra credit Implement an overloaded constructor for the Player class that accepts 4 int parameters (Number, Hits, Walks, Outs). You will need to modify the file Player.java Copy your solution to a file named Baseball88.java and further modify the program to produce identical output to Baseball8.java but invoke the overloaded constructor when you come to steps 7) and 7a) in the main() method s algorithm to initialize the corresponding Player data attributes with the values that were input. Use the commands make -k baseball88, java Baseball88 and submit csc156abc 88 to compile, execute and submit your assignment, respectively. This problem is related to an inventory update algorithm whereby different products have arrived within different shipments over periods of time. As the shipments arrive, we need to update the records in the data base so that we have an accurate record of the number of products (identified by the product number) that are within the inventory. So, as the Player on the team[] accumulates more Hits, Walks and Outs, we increase the number of those attributes that are in storage. Of course, in the inventory model, products are also sold or shipped to another warehouse causing us to decrease the numbers that we have on hand. That part of the algorithm will not be necessary in the baseball model. Assignment 8 Specifications: Process connect to the input file baseball.txt and set the team size to 0 Output a descriptive message about the program Process declare an array of length 20 to hold the instances of class Player Process loop over the elements of the array Process instantiate each object within the array of Player Process repeat until the end-of-file Input the Player Number, the Hits, the Walks and the Outs Process search for the Player Number within the initialized array values Process if the Player Number is not already in the array Process store the Player s Number, Hits, Walks and Outs Process else update the Player s Hits, Walks and Outs Output display the Player s Number, the total numbers of Hits, Walks and Outs Process disconnect from the input file baseball.txt Object Analysis and Algorithmic Development The main() method for this program is in the file Baseball8.java. The code in the start-up file connects to the sequential input file baseball.txt and inputs all of the int values in the file, but does not produce any output beyond the informational message. We ll need to remember to disconnect from the input file when we re done. Once again, all output should be displayed to the monitor. 1. process to connect the input file fin to the program and set teamsize to 0 2
2. output an informational message to the screen about the program 3. process declare an array of length 20 of type Player named team[] (a) process for each value of i from 0 to 19 (b) process instantiate array element team[i] 4. process while not-end-of-file fin (a) input the Number, Hits, Walks and Runs of a Player (b) process determine if the Number is stored in the first teamsize elements (c) process if the Number is not stored in the array i. process Number of teamsize is argument to setnumber() ii. process Hits of teamsize is argument to sethits() iii. process Walks of teamsize is argument to setwalks() iv. process Outs of teamsize is argument to setouts() v. process increase teamsize by 1 (d) process else if team[index] contains Number i. process Hits + gethits() of index is argument to sethits() ii. process Walks + getwalks() of index is argument to setwalks() iii. process Outs + getouts() of index is argument to setouts() 5. output display Player s Number, Hits, Walks, Outs 6. process disconnect from the file fin Control structures represented above include steps 3.a and 3.b that are coded with a for statement to instantiate the array elements, steps 4.(a) through 4.(d) that are coded as an end of file while statement, and steps 4.(c) and 4.(d) that represent the true and false clauses of an if statement. When we implement the sequential search algorithm below, we ll design it to return -1 if the Player Number is not within the first teamsize elements of the array team[] and the index of the array team[] where Number is stored otherwise. Lines that are displayed in blue represent areas where you ll need to write or modify code to complete this assignment. Pseudo Code for the main() Method Statement Data objects 1a) connect to input file fin Scanner wrapped around a FileReader & String 1b) initialize the teamsize to 0 int objects 2) output an informational message System.out and String objects 3) declare array of type Player of size 20 Player array & int object 3a) loop over int values from 0 to 19 int objects 3b) instantiate i th array element int object, Player array and constructor 4) loop on end of file fin Scanner wrapped around a FileReader methods 5) input the Number, Hits, Walks, & Outs from fin Scanner wrapped around a FileReader & int objects 6) find the index of this Number method findnumber(), Player array & int objects 7) if index < 0 int objects 7a) store Number, Hits, Walks & Outs in Player array methods & int objects team[teamsize] 8) else 8a) update team[index] s Hits, Walks & Outs Player array methods & int objects. 9) output the team[] data by invoking displayarray method Player array & int objects displayarray() 10) disconnect from input file fin fin.close() method 3
To clarify the above structure, steps 5)-8) are in the while loop at step 4). Step 7a is in the true path of the if statement of step 7) and steps 8) and 8a) are the false path of that if. The method findnumber() should be coded in the file Baseball8.java and should implement a sequential search of the array team[] looking for the first occurrence of the parameter Number and should return either -1 upon failure to find the Number or the index into team[] where Number is stored otherwise. The method will also need a parameter to know the team size to control the looping through the Player array. 1. process initialize an int variable Save to -1 and assume that Number is not in array team[] 2. process loop over indices 0 through team size - 1 3. if team[index] is equal to Number (a) update Save to the index value (b) break from the loop 4. return Save To clarify the structure above, step 3) is in the loop that is at step 2). Steps 3a) and 3b) are on the true path of the if statement at step 3). Pseudo Code for the findnumber() Method Statement Data objects 1) assume failure and set Save to -1 int objects 2) loop over index from 0 to team size - 1 int objects 3) test Number less than 0 Player team[index] method & int objects 4) set Save to index & break int objects 5) return the value in Save int objects The method displayarray() simply displays some column headings and then loops through the team size elements of the array team[], displaying each Player. It is left as an exercise to develop. Coding for Compilation Logon to your csc.oakton.edu account and create a new subdirectory of the labs directory called 8 to work on your assignment. cd labs mkdir 8 cd 8 You ll need to copy the makefile, Baseball8.java and baseball.txt files that are provided over to your local directory by issuing the following command. cp /samples/csc/156/labs/8/*. emacs Baseball8.java & Examine the contents of Baseball8.java as compared to our discussion above. We ve provided you with a compilable program that loops through the contents of the file. When we use input files, problems or exceptions can arise. There are several ways to deal with such problems using the catch and throw commands that we will not amplify here. What we will do is identify the most common error that occurs with files (it can t be found) and will identify that the main() method throws a FileNotFoundException. Since we ve coded the Player class before the first Checkpoint, we re ready to examine and add to the code in Baseball8.java to complete the assignment. Note that steps in blue represent lines of code that you should author to complete the assignment. 4
The Object Player CSC 156 - Assignment 8 Baseball Before we discuss the various methods to manipulate the Player objects, we should discuss the construction of the object itself. This occurs in the file Player.java in a Java class. There are 4 data attributes that should be private of type int. Each instance of a Player class will need their own separate copies of these variables. Declare these within the class, but separate from any methods so that they will exhibit class scope. Obvious names for these would be Number, Hits, Walks and Outs. The general format of the Player class requires the use of a class statement in the file Player.java that looks like the following. public class class name declarations; statement 1 ; statement 2 ;. statement n ; We ll want everyone to have access to the class, and so we ll want that to be public. However, we ll not want everyone to have direct access to the data attributes stored in the Player and so we ll need to identify those as private. The code for the class statement necessary that includes the data attributes that we ve described above is as follows. public class Player private int Number, Hits, Walks, Outs; Constructors The support of object declaration and initialization is the responsibility of the constructor method. Typically, constructors support both uninitialized object instantiation as well as initialized. Our constructor will only support default initialization that sets each data attribute to zero. Constructors have no return type and are named after the class. The code for this constructor within the Player class would look as follows. public class Player private int Number, Hits, Walks, Outs; public Player() int Number = Hits = Walks = Outs = 0; Extractors The purpose of the extractor is to return information about the object without modifying the object. This is how we ll support knowledge of what data is stored in the Player without providing direct access to the private data attributes. We can name the extractor any valid Java name, but it is very popular to name an extractor get(). Given the declared Player objects discussed above, we will need one extractor for each data attribute. 5
These should be named getnumber(), gethits(), getwalks() and getouts() and should all return type int. We ll show the code for the getnumber() extractor, the others are similar. public class Player private int Number, Hits, Walks, Outs; public Player() int Number = Hits = Walks = Outs = 0; public int getnumber() return Number; Mutators The purpose of the mutator is to modify information stored in the object. This is how we ll support modifying the data stored in the Player without providing direct access to the data attributes. We can name the mutator any valid Java name, but it is very popular to name them set(). You will need 4 mutator methods, each returning void with an int parameter. These simply set each of the data attributes equal to the value of the parameter and should be named setnumber(), sethits(), setwalks() and setouts(). We ll show the code for the sethits() mutator, the others are similar. public class Player private int Number, Hits, Walks, Outs; public Player() int Number = Hits = Walks = Outs = 0; public int getnumber() return Number; public void sethits( int h ) Hits = h; tostring() Methods For output, the Java language takes advantage of the fact that all displayed objects have a String representation. The strategy is to overload a method called tostring() that has no parameters and returns a String representation of the object to be displayed.we ll conclude this discussion by implementing the output of Player objects below. Given that we have numeric data that we wish to display, it may be in our interest have this method return an instance of String.format() so that the values within the return value are formatted appropriately. public class Player 6
private int Number, Hits, Walks, Outs; public Player() int Number = Hits = Walks = Outs = 0; public int getnumber() return Number; public void sethits( int h ) Hits = h; public String tostring() String s = new String(); s = String.format("%2d", Number) + "\t" + String.format("%2d", Hits) + "\t" + String.format("%2d", Walks) + "\t" + String.format("%2d", Outs); CSC 156 - Assignment 8 Baseball Figure 1 displays a Unified Modeling Language (UML) diagram of the Player class. Player -Number : int -Hits : int -Walks : int -Outs : int +Player() +getnumber() : int +gethits() : int +getwalks() : int +getouts() : int +setnumber(int) : void +sethits(int) : void +setwalks(int) : void +setouts(int) : void +tostring() : String Figure 1: Lab 8 Player Unified Modeling Language Diagram Checkpoint 1 Let s see if we can get this much of our program to compile before proceeding. Save your program to disk by choosing the Save command from the Files menu of your emacs session. Then, compile your program by choosing the Compile... command from the Tools menu and change the make -k that is displayed to make -k baseball8 Compiler errors can be parsed with the keystroke C-x and need to be repaired before proceeding. Execute your program with the command java Baseball8 You should see the display of the informational message. We ll have another Checkpoint later to examine the complete solution of the assignment. 7
Declaration of Variables CSC 156 - Assignment 8 Baseball The variables to be declared within the main(), findnumber() and displayarray() methods have been discussed in the pseudo-code above. Follow the Pseudo-code for main() Step 1) // connect to input file fin and initialize teamsize to 0 This declaration wraps a FileReader object with a Scanner object so that we can use Scanner methods that were similar to what we used when input came from the keyboard. Scanner fin = new Scanner(new FileReader("baseball.txt")); The variable teamsize is simply an int value that can be initialized at declaration. Step 2) // output an informational message This is no different than other monitor output messages that we ve been coding since the first days of the course. Step 3) // declare array of type Player of size 20 The array should be declared like any other array, so this step will follow the general format for such declarations. We ll assume that the name of this array is team[]. Player [] array name = new Player[array size]; Steps 3a-3b) // loop over int values from 0 to 19 // instantiate the i th array element What you ll now need to do is invoke your constructor Player() for each array element. Code a for loop that loops from 0 to 19 and set the i th array element to new Player(). Step 4) // loop on the end of file condition This code has already been supplied for you in the file Baseball8.java. It is no different that we ve used in previous assignments. Step 5) // input the team number from fin // input that player s hits from fin // input that player s walks from fin // input that player s outs from fin Once again, we take advantage of the Scanner methods for these lines of code. Note that the int variables from the main() method that hold the input values are distinct from the attribute variables for each instance of the Player class (Hits, Walks, Outs). 8
Step 6) CSC 156 - Assignment 8 Baseball // find the index of this Player s number Our recommendation is that you code this statement as a comment as it will be helpful to compile what you ve coded at the next Checkpoint before you code the method findnumber(). This is an invocation of the method findnumber(). You will need to save this return value as an index into the array when the search is successful. The parameters will include the array team[], the Number that you re searching for and the teamsize. Step 7) // test for new number in the list This is simply an if statement that assumes that the return value of method findnumber() will return a negative value when the Number sent to it at the previous step is not found. Step 7a)-7e) // set the Number field for team[teamsize] // set the Hits field for team[teamsize] // set the Walks field for team[teamsize] // set the Outs field for team[teamsize] // increase teamsize by 1 Since the Number was not found in the list, we ll simply put it at the end of the list. For each of the data attributes, invoke team[teamsize].sethits() or team[teamsize].setwalks() or team[teamsize].setouts() before increasing teamsize by 1. Step 8) // else This is the false path of the if statement of step 7). Steps 8a)-8c) // update the Hits field for team[index] // update the Walks field for team[index] // update the Outs field for team[index] Since the Number was found in the list, there s no need to store Number or increase the teamsize. We ll need to increase the Hits, Walks and Outs data attributes using the index variable that was returned by the method findnumber(). The manned in which to do this is to compose the two methods get with set that are available for each of the data attributes. We ll provide the code for updating the Hits where we assume that the variable hits represents the number of Hits input for this Player s Number in the main() method. The method invocations for Walks and Outs are similar. team[index].sethits(hits + team[index].gethits()); Step 9 // display the results This will be an invocation of the method displayarray(). You will need to send the array team[] and the teamsize as parameters. Step 10 // disconnect from input file fin All files that are opened should be disconnected. This line has been provided for you. 9
fin.close(); Checkpoint 2 Save your program to disk by choosing the Save Buffer command from the Files menu of your emacs session. Then, compile your program by choosing the Compile... command from the Tools menu and change the make -k that is displayed to make -k baseball8. Compiler errors can be parsed with the keystroke C-x and need to be repaired before your program can execute. This keystroke will also ensure that the correct file is in the buffer to examine lines that generated compiler errors. When your program has compiled, we ll need to move on to code the method findnumber() before we can execute it. Follow the Pseudo-code for method findnumber() This method returns an int value that will be -1 when the search is not successful, and a value that we ve been referring to as index when it is successful. The post condition of the method is -1 index < team size. The parameters for the method are the array team[], the Player Number, and the team size. Step 1) // assume that this Number is not in the list This is accomplished by declaring a local int variable Save that is initialized to -1. Step 2) // loop over the list length This is a for statement that loops over the indices from 0 through team size - 1. Step 3) // exit the loop if the Number is found This is an if statement that tests the equality of Number and team[i].getnumber(). When this condition is true, you should store the index in the variable Save and exit the for statement. Step 4) // return either the found index or -1 in variable Save If the loop completes its execution and never finds the Number, then the value stored in Save at Step 1 will never have been updated and the method returns -1. If the condition at Step 3 every occurs, the loop is exited immediately and the method returns the index into team[] where the Number is stored. Once you ve coded the method findnumber(), you can remove the comment that you placed in Step 6 with the invocation of the method. At this point, you should recompile and execute your program. Testing for errors The usual source of errors in these types of programs can occur in one of 3 areas. The use of the files, the use of the arrays and the use of the classes. The file activity here was given to you and if you follow the pseudo code that was given with file activity, you should not have a problem with those commands. The most common problem with the use of the arrays is the index variable. If you see an ArrayIndexOutOfBounds error message, the error is in the manner in which you re accessing the array element. The index into the array is either too large or negative. The possible error with the classes could be in the algorithms for the method. Recall that all the constructor should do is to set each attribute variable to 0. Each extractor should simply return its corresponding attribute variable, and each mutator should set it s attribute variable to the value of its parameter. If you re stuck with those simple algorithms, the only other place where something could go wrong is when you 10
update the attribute variable within the end of file loop. There is a correct version of the output of this program at this link. Printing and submitting Once you are satisfied with the correctness of your program, print it as you did with previous assignments by using the following command that assumes that you are working in the room 1234 at Oakton. Retrieve your copy from the printer. printer 1234 Player.java printer 1234 Baseball8.java Finally, submit your program with the following command that assumes that you are registered in section abc of CSC 156. submit csc156abc 8 11