I am looking for feedback on a solution to the following problem posed from a book that I'm working through (Java: How To Program 9th Edition):
Continuing the discussion in Exercise 16.20, we reiterate the importance of designing check-writing systems to prevent alteration of check amounts. One common security method requires that the amount be written in numbers and spelled out in words as well. Even if someone is able to alter the numerical amount of the check, it’s extremely difficult to change the amount in words. Write an application that inputs a numeric check amount that’s less than £1000 and writes the word equivalent of the amount. For example, the amount 112.43 should be written as
ONE hundred TWELVE and 43 pence
I'm interested in solutions which cover the areas I have studied so far, those being:
- Introduction to Computers and Java
- Introduction to Java Applications
- Introduction to Classes, Objects, Methods and Strings
- Control Statements: Part 1
- Control Statements: Part 2
- Methods: A Deeper Look
- Arrays and ArrayLists
- Classes and Objects: A Deeper Look
- Object-Oriented Programming: Inheritance
- Object-Oriented Programming: Polymorphism
- Exception Handling: A Deeper Look
- GUI Components: Part 1 (Swing)
- Strings, Characters and Regular Expressions
I have been a bit naughty by jumping ahead of the text to use a little recursion within the readMe()
method. I figured from the description of recursion that the line of code in question would behave this way and I was right.
I can't help feeling that the way I have implemented the readMe()
method is somewhat messy and I can see that it would not scale very well beyond £1000 or four digits. Is there a simpler way of doing this? All forms of feedback are welcome.
import java.util.Scanner;
public class WordCheckAmount {
public static void main(String[] args) {
Scanner sc = new Scanner( System.in );
String userInput;
boolean correctInput = false;
do
{
System.out.println( "Please enter an amount below 1000" );
userInput = sc.nextLine();
System.out.println();
if( userInput.indexOf( '.' ) < 0 && validateAmount( userInput ) ) // no decimal point
{
correctInput = true;
readMe( userInput );
}
if( userInput.indexOf( '.' ) > 0 && validatePointAmount( userInput ) ) // decimal point
{
correctInput = true;
String[] tokens = userInput.split( "\\." );
readMe( tokens[ 0 ] );
System.out.printf( "and " );
readMe( tokens[ 1 ] );
System.out.println( "pence" );
}
}while( !correctInput );
}
public static boolean validatePointAmount( String amount )
{
return amount.matches( "\\d{0,3}.?\\d{0,2}" );
}
public static boolean validateAmount( String amount )
{
return amount.matches( "\\d{0,3}" );
}
public static void readMe( String amount )
{
String[] oneThruNineteen = { "NULL", "ONE", "TWO", "THREE", "FOUR", "FIVE", "SIX",
"SEVEN", "EIGHT", "NINE", "TEN", "ELEVEN", "TWELVE",
"THIRTEEN", "FOURTEEN", "FIFTEEN", "SIXTEEN", "SEVENTEEN",
"EIGHTEEN", "NINETEEN" };
String[] theDecades = { "NULL", "NULL", "TWENTY", "THIRTY", "FOURTY", "FIFTY",
"SIXTY", "SEVENTY", "EIGHTY", "NINETY" };
int theLength = amount.length();
switch( theLength )
{
case 3: // 3 digits
System.out.printf( "%s ", oneThruNineteen[ Character.getNumericValue( amount.charAt( 0 ) ) ] );
System.out.printf( "hundred " );
int testMe = Character.getNumericValue( amount.charAt( 1 ) );
if( testMe < 2 ) // if tens unit in the teens
System.out.printf( "%s ", oneThruNineteen[ Integer.parseInt( amount.substring( 1, 3 ) ) ] );
else // if tens unit twenty or higher
{
String feedMe = amount.substring( 1 , 3 );
readMe( feedMe ); // recursion I presume? feedback for 2 digits
}
break;
case 2: // 2 digits
int testMe2 = Character.getNumericValue( amount.charAt( 0 ) );
if( testMe2 < 2 ) // if tens unit in the teens
System.out.printf( "%s ", oneThruNineteen[ Integer.parseInt( amount ) ] );
else // if tens unit twenty or higher
{
System.out.printf( "%s ", theDecades[ Character.getNumericValue( amount.charAt( 0 ) ) ] );
int testMe3 = Character.getNumericValue( amount.charAt( 1 ) );
if( testMe3 > 0 ) // if next digit is higher than 0, otherwise you get TWENTY NULL for 20 etc
System.out.printf( "%s ", oneThruNineteen[ Character.getNumericValue( amount.charAt( 1 ) ) ] );
}
break;
case 1: // just the 1 digit
System.out.printf( "%s ", oneThruNineteen[ Integer.parseInt( amount ) ] );
break;
}
}
}