390 likes | 514 Views
Methods and Formatted Output. Chapter 4. Overview. Breaking down a big program into small methods. Formatting output using printf using DecimalFormat. Methods. Methods are similar to friends . You can ask them to do you a favor.
E N D
Methods and Formatted Output Chapter 4
Overview • Breaking down a big program into small methods. • Formatting output • using printf • using DecimalFormat
Methods • Methods are similar to friends. • You can ask them to do you a favor. • You can send some data to them (or you can call them without sending data). • You can get back at most one piece of data (or no data). • For example, the printlnmethod is like a friend that does some printing. You send the method the data and he does the printing. The method does not return any information. • Conversely, the nextIntmethod takes no input. However, it returns back an integer.
Example Program import java.util.*; public class Remodel { public static void main(String[] args) { callBob(); callPeter(); } public static void callBob() { System.out.println("Paint room"); } public static void callPeter() { System.out.println("Install hardwood floor"); } }
Notes • For now, all methods are public and static. • Calling a method transfers the flow of control to the method. Once the method is executed, control goes back to the calling method (main in our case). • Method names start with a lowercase letter. • We must always use parenthesis, i.e. method_name( ... ) when calling a method. This tells Java that we are calling a method and not referencing to a variable. • A method must have a return type. Use void when it does not return anything.
import java.util.*; public class Remodel { public static void main(String[] args) { double bobPrice = callBob(8, 12); double peterPrice = callPeter(8, 12); double totalPrice = bobPrice + peterPrice; System.out.println("Total price for the project: $" + totalPrice); } public static doublecallBob(int width, int length) { System.out.println("Paint room"); double pricePSF = 0.80; return pricePSF * width * length; } public static doublecallPeter(int width, int length) { System.out.println("Install hardwood floor"); double pricePSF = 3.20; return pricePSF * width * length; } }
Notes • Two ways to call a method: • m(...) <- use when method does not return anything (void method) and • a = m( ...) <- use when method returns a value. • When a method returns a value, we must save the value (or use it directly, e.g., print it). • A common mistake is to call a method that computes something, but do not save the result. Then all the work that is done by the method will go to waste.
Atomic Variables • Instance (i.e. non-static) variables in Java are atomic (i.e., memory for them is automatically allocated and freed). • The memory for a variable is allocated when the variable is defined. • The memory is freed when the block in which the variable is defined finishes. • Note that the variable is NOT valid outside the block in which it is defined. • When a method is called, the variables of the first method will not be valid inside the method that is called.
Formal vs. Actual Parameters • The formal parameters are defined in the signature of the method: • public static double callPeter(intwidth, intlength) {...} • Formal parameters are basically local variable for the method. They are only defined inside the method. • Actual parameters are the parameters that are sent to the method: • double bobPrice = callBob(8, 12); • These could be literals,variables,or expressions. • The formal parameters are initialize by the value of the actual parameters. • Changing the value of a formal parameter variable does not change the value of an actual parameter variable.
Example Code intx = 3;inty = 5;callBob(x,y); • Note thatthemethodcall cannot change the value of the variables x and y. • Any change to these variables inside the callBob method will only change the formal (i.e., local for the method variables) and not the actual parameters.
The return Statement • Performs two tasks: • always exits the method (including a void method) and • returns back exactly one piece of information (or nothing for void methods). • Use the following syntax when a method returns a value. • a= m( ...) or • System.out.println(m(...)) • Never use just m(...) when a method returns a value. All the work to compute the result will be wasted.
Formatting Output Using printf • Example: System.out.printf(" $%.2f on painting and"+ " $%.2f on hardwood for total of $%.2f,", bobPrice, peterPrice, totalPrice); • Method has variable number of arguments. • The first parameter is the string that is printed. • Whenever a %... is found in the first parameter, it is replaced with the next parameter in the list. • %.2f means display a float (or a double) with 2 digits after the decimal dot.
Examples Using printf Remember that %d stands for decimal, not float!
Formatting Real Numbers Using printf • %.3f -> 3 digits after the decimal dot. Result is rounded. • For example: printf("%.3f",2.998) will print 3.000 • %6.2f -> 2 digits after the decimal dot and at least 6 total characters • For example, printf("7.3f",2.998) will print " 3.000", where there are 2 spaces at front. • %-7.2f will justify it to the right. • For example, printf("7.3f",2.998) will print "3.000 ", where there are 2 spaces at the back.
Formatting Output Using DecimalFormat public class Test { public static void main(String[] args){ DecimalFormatmyFormatter = new DecimalFormat("$###,###.00"); System.out.println(myFormatter.format(32536.34)); } } // will print $32,536.34 • Used when we want to format output using special characters, e.g. $32,536.34 is the output of the program. • # means there may or may not be a number there • 0 means there must be a number. If there is no number, put 0. public class Test { public static void main(String[] args){ DecimalFormatmyFormatter = new DecimalFormat("$000,000.00"); System.out.println(myFormatter.format(32536.34)); } }// will print $032,536.34
Code Refactoring • Refactoring meaning rewriting code without changing what it does. • We want the code to be very clean and self-explanatory. • Want to use methods. • Every method must perform a single task. If a method performs multiple tasks, break it down into several methods. • Try to make methods reusable. A method that makes a stickman jump and scratch their ear will not be reusable. Instead, create jump method and scratch ear methods. • If you have code that repeats multiple times, then try to move it to a method. This will make the code more compact and easy to understand. • Always give methods meaningful names.
Previous Code to Print Diamond for (intnumStars =1, numSpaces = size-1; numSpaces >=0 ; numSpaces-=2, numStars+=2){ for (int i = 0; i < numSpaces; i++) { System.out.print(" "); } for (int i = 0; i < numStars; i++) { System.out.print("* "); } System.out.println(); } for (intnumStars=size-2, numSpaces = 2; numStars >=0 ; numSpaces+=2, numStars-=2 ) { for (int i = 0; i < numSpaces; i++) { System.out.print(" "); } for (int i = 0; i < numStars; i++) { System.out.print("* "); } System.out.println(); }
import java.util.*; public class Diamond { public static void printStrings(String s, int n){ for(int i=0; i < n; i++){ System.out.print(s); } } public static void main(String[] args) { Scanner keyboard = new Scanner(System.in); System.out.print("Enter size of diamond: "); int size = keyboard.nextInt(); for (intnumStars =1, numSpaces = size-1; numSpaces >=0 ; numSpaces-=2, numStars+=2) { printStrings(" ",numSpaces); printStrings("* ",numStars); System.out.println(); } for (intnumStars=size-2, numSpaces = 2; numStars >=0 ; numSpaces+=2, numStars-=2 ) { printStrings(" ",numSpaces); printStrings("* ",numStars); System.out.println(); } } }
import java.util.*; public class Diamond { public static void printStrings(String s, int n) { ... } public static void printLine(intnumSpaces, intnumStars) { printStrings(" ", numSpaces); printStrings("* ", numStars); System.out.println(""); } public static void main(String[] args) { Scanner keyboard = new Scanner(System.in); System.out.print("Enter size of diamond: "); int size = keyboard.nextInt(); for (intnumStars = 1, numSpaces = size - 1; numSpaces >= 0; numSpaces-= 2, numStars += 2) { printLine(numSpaces,numStars); } for (intnumStars = size - 2, numSpaces = 2; numStars >= 0; numSpaces+= 2, numStars -= 2) { printLine(numSpaces, numStars); } } }
Self-Documenting Code • Always choose proper names for methods and variables (starting with small letter). • The name of a method should explain what the method does. • For example, the code on the last slide is self-explanatory, we do not need any documentation. The method printLine prints a line of the diamond, for example. • Create a method for every task and name the method appropriately (describing what is the task). For big tasks, a method can call other methods to execute sub-tasks. For example, the printLinemethod calls the printStrings method.
Documenting Methods using JavaDoc • In NetBeans, Type /** • A template magically appears. • Can be typed before a method or a class. • Fill in the missing pieces. • For methods, describe method purpose and parameters. • For classes, describe class purpose. • Can be used to generate HTML JavaDoc file. • Just go to Run: Generate JavaDoc
JavaDoc Example /** * Prints a string multiple times on the same line. * @param s The string to be printed. * @param n The frequency. */ public static void printStrings(String s, int n) { for (int i = 0; i < n; i++) { System.out.print(s); } }
Pass by Value • Primitive types, e.g., int, double, etc., are passed by value. • This means that a method cannot modify input parameters of these types. • The variables for the formal parameters are local variables and they can change in a method. • However, the calling method will not see the changes.
What will be printed? import java.util.*; public class Example{ public static void inc(int i){ i++; } public static void main(String[] args) { int i = 3; inc(i); System.out.println(i); } }
What About Now? import java.util.*; public class Example{ public static intinc(int i){ i++; return i; } public static void main(String[] args) { int i = 3; i = inc(i); System.out.println(i); } }
Third Example import java.util.*; public class Example{ static int i; public static void inc(){ i++; } public static void main(String[] args) { i = 3; inc(); System.out.println(i); } }
Method return type • A method can return only one piece of data. • If a method needs to return multiple pieces of data, then there are several options. • Define the data global. The method can have void return type and will have access to the data. • Break the method into several methods. Each method can return one piece of the data.
The Trading Game • We can trade apples and pears. • The game has 10 days. • Every day the price changes randomly. • The goal is to make the most $$$. • Every day we can buy or sell apples or pears. • We start with $100. • There are restrictions. • We can't buy more than what we can afford. • We can't sell if we don't have the inventory. • We will use a top-down approach to implement the game. • We will first write the main method that calls other methods. The other methods will be written later.
import java.text.*; import java.util.*; public class TradingGame { static finalint NUMBER_OF_DAYS=10; static final double BASE_PRICE = 10; static final double VARIATION = 5;//in $ static final double INITIAL_CASH=100; static double cash = INITIAL_CASH; static intappleInventory = 0; static intpearInventory = 0; static double applePrice, pearPrice; public static void main(String[] args) { for (int day = 1; day <= NUMBER_OF_DAYS; day++) { applePrice = computePrice(BASE_PRICE, VARIATION); pearPrice = computePrice(BASE_PRICE, VARIATION); System.out.println("Day: " + day + " out of 10"); int choice; do{ printMenu(); choice = getChoice();
switch (choice) { case 1: // Print cash balance and inventory System.out.println("Cash: " + currencyFormatter(cash)); System.out.println("Apple inventory: "+appleInventory); System.out.println("Pear inventory: "+pearInventory); break; case 2: //Print today's prices System.out.println("Price of apples is: "+ currencyFormatter(applePrice)); System.out.println("Price of pears is: "+ currencyFormatter(pearPrice)); break; case 3: { //Buy apples int amount = getQuantity("apples", "buy"); if (!buyApples(amount)) { System.out.println("You don't have enough money"); } break; } case 4: { // Sell apples int amount = getQuantity("apples", "sell"); if (!sellApples(amount)) { System.out.println("You don't have enough apples"); } break;}
case 5: { // Buy Pears int amount = getQuantity("pears", "buy"); if (!buyPears(amount)) { System.out.println("You don't have enough money"); } break; } case 6: { // Sell Pears int amount = getQuantity("pears", "sell"); if (!sellPears(amount)) { System.out.println("You don't have enough pears"); } break; } } } while (choice != 7); } System.out.println("You finished with:"+ currencyFormatter(cash)); } ... }
Notes • Constants are defined as static final. All constants are defined at the beginning of the code. Constants use all capital letters. • Lots of global variables. The reason is that most methods need to return several piece of data. For example, buyApples updates cash and appleInventory. In addition, it returns a Boolean value: was the operation successful. • Price of apples and pairsranges in the interval: (BASE_PRICE -VARIATION, BASE_PRICE+VARIATION) • getQualitymethod is used to get amount for buy/sell of apples/pairs.
public static void printMenu() { System.out.println("1.Print cash balance and inventory"); System.out.println("2.Print today's prices"); System.out.println("3.Buy apples"); System.out.println("4.Sell apples"); System.out.println("5.Buy pears"); System.out.println("6.Sell pears"); System.out.println("7.I am done for today"); } public static intgetChoice() { Scanner keyboard = new Scanner(System.in); int choice; do { System.out.print("Your choice: "); choice = keyboard.nextInt(); } while (choice > 7 || choice < 1); return choice; } public static String currencyFormatter(double amount) { DecimalFormatmyFormatter = new DecimalFormat("$#,###.00"); return myFormatter.format(amount); }
public static double computePrice(double basePrice, double variation) { double result = basePrice; if (Math.random() > 0.5) { result += Math.random() * variation; } else { result -= Math.random() * variation; } return ((int)(result*100))/100.0;//makes price 23.23 } public static intgetQuantity(String product, String action) { System.out.print("How many " + product + " do you want to " + action + "? "); Scanner keyboard = new Scanner(System.in); return keyboard.nextInt(); } public static booleansellApples(int amount) { if (amount > appleInventory) { return false; } cash += amount * applePrice; appleInventory -= amount; return true; }
public static booleansellPears(int amount) { if (amount > pearInventory) { return false; } cash += amount * pearPrice; pearInventory -= amount; return true; } public static booleanbuyApples(int amount) { if (amount * applePrice < cash) { cash -= amount * applePrice; appleInventory += amount; return true; } return false; } public static booleanbuyPears(int amount) { if (amount * pearPrice < cash) { cash -= amount * pearPrice; pearInventory += amount; return true; } return false; }
Notes • The buy/sell methods check to see if the operation is possible. If it is not, they return false. • The methods modify global variables. • Every method performs one task. Can't easily combine buy/sell methods. • We used DecimalFormat to format output. • The following code is possible, but not preferred (too cryptic). public static double computePrice(double basePrice, double variation) { return ((int)((basePrice + (Math.random() > 0.5 ? 1 : -1) * variation)*100))/100.0; } • ((int)(result*100))/100.0; //Saves 2 digits after the dot.
Conclusion • Use methods to break a big problem into smaller problems. • Methods can be used to avoid repeating the same code multiple times. • Methods should be short and perform a single task. • Avoid writing methods that do one of several things based on input parameter. • Methods cannot modify input data of primitive type. • Methods can return back only a single piece of data. • Use printf and DecimalFormat for formatted printing.