New to Java? We'll help you get started with our revised beginner's tutorial, or our free online textbook.


Get the latest Java books
h t t p : / /w w w . j a v a c o f f e e b r e a k . c o m /

Java Coffee Break

Solution for
Programming Exercise 4.1


THIS PAGE DISCUSSES ONE POSSIBLE SOLUTION to the following exercise from this on-line Java textbook.

Exercise 4.2: The hexadecimal digits are the ordinary, base-10 digits '0' through '9' plus the letters 'A' through 'F'. In the hexadecimal system, these digits represent the values 0 through 15, respectively. Write a function named hexValue that uses a switch statement to find the hexadecimal value of a given character. The character is a parameter to the function, and its hexadecimal value is the return value of the function. You should count lower case letters 'a' through 'f' as having the same value as the corresponding upper case letters. If the parameter is not one of the legal hexadecimal digits, return -1 as the value of the function.

A hexadecimal integer is a sequence of hexadecimal digits, such as 34A7, FF8, 174204, or FADE. If str is a string containing a hexadecimal integer, then the corresponding base-10 integer can be computed as follows:

               value = 0;
               for ( i = 0; i < str.length();  i++ )
                  value = value*16 + hexValue( str.charAt(i) );

Of course, this is not valid if str contains any characters that are not hexadecimal digits. Write a program that reads a string from the user. If all the characters in the string are hexadecimal digits, print out the corresponding base-10 value. If not, print out an error message.


Discussion

The subroutine has a parameter of type char and a return value of type int. It's easy to write the switch statement, although it's tedious because of the number of cases. A little creative cut-and-paste can help. The switch statement has a default case that covers all the characters that are not hexadecimal digits. For such characters, a value of -1 is returned. The subroutine is shown in the program below, and I will not repeat it here.

In the main program, I will use TextIO.getlnWord() to read the user's input, rather than TextIO.getln(). This has the advantage that it will return a non-empty string that is guaranteed not to contain any blanks. We still have the problem of checking whether the user's input contains only valid hexadecimal digits. One approach is to check all the characters first and use a boolean variable to record whether they are all valid. Let hex be a string holding the user's input. Then we have:

         boolean valid;
         valid = true;  // Assume that the input is valid, and change our
                        // mind if we find an invalid character.
         for ( i = 0; i < hex.length(); i++ ) {
             if ( hexValue(hex.charAt(i)) == -1 ) {  // Character number i is bad.
                valid = false;
                break; // Leave the for loop, since we are now sure of the answer.
             }
         }
         if ( valid ) {  // If the input is valid, compute and print base-10 value
            dec = 0;
            for ( i = 0; i < hex.length(); i++ )
               dec = 16*dec + hexValue( hex.charAt(i) );
            System.out.println("Base-10 value is:  " + dec);
         }
         else {  // Input is not valid, print an error message
            System.out.println("Error:  Input is not a hexadecimal number.");
         }

This works, but we have to process the string twice. We can avoid this by checking the input at the same time that we do the conversion. If the input is illegal, I want to end the program. I use the fact that a return statement in the main() routine will end the program, since it returns control back to the system:

          dec = 0;
          for ( i = 0; i < hex.length(); i++) {
             int digit = hexValue( hex.charAt(i) );
             if (digit == -1) {
                 TextIO.putln("Error:  Input is not a hexadecimal number.");
                 return;  
             }
             dec = 16*dec + digit;
          }
          TextIO.putln("Base-10 value:  " + dec);

This is the code that is used in the main() routine of the program to do the conversion. Note that I declared dec to be of type long to allow bigger values than would fit in a variable of type int. The program still has a problem if the user enters too many characters. (It gets the wrong answer.)

It would probably be better to write a function to do the conversion of a string to base-10. It could return a -1 if the string is not a legal hexadecimal number. The main() routine could then call the function and check its return value to find out whether there was an error.


The Solution

    public class Hex2Dec {
      
       /*  This program reads a hexadecimal number input by the
           user and prints the base-10 equivalent.  If the input
           contains characters that are not hexadecimal numbers,
           then an error message is printed.
       */
    
       public static void main(String[] args) {
          String hex;  // Input from user, containing a hexadecimal number.
          long dec;    // Decimal (base-10) equivalent of hexadecimal number.
          int i;       // A position in hex, from 0 to hex.length()-1.
          TextIO.put("Enter a hexadecimal number: ");
          hex = TextIO.getlnWord();
          dec = 0;
          for ( i = 0; i < hex.length(); i++ ) {
             int digit = hexValue( hex.charAt(i) );
             if (digit == -1) {
                 TextIO.putln("Error:  Input is not a hexadecimal number.");
                 return;  
             }
             dec = 16*dec + digit;
          }
          TextIO.putln("Base-10 value:  " + dec);
       }  // end main()
       
       static int hexValue(char ch) {
             // Returns the hexadecimal value of ch, or returns
             // -1 if ch is not one of the hexadecimal digits.
          switch (ch) {
             case '0':
                return 0;
             case '1':
                return 1;
             case '2':
                return 2;
             case '3':
                return 3;
             case '4':
                return 4;
             case '5':
                return 5;
             case '6':
                return 6;
             case '7':
                return 7;
             case '8':
                return 8;
             case '9':
                return 9;
             case 'a':
             case 'A':
                return 10;
             case 'b':
             case 'B':
                return 11;
             case 'c':
             case 'C':
                return 12;
             case 'd':
             case 'D':
                return 13;
             case 'e':
             case 'E':
                return 14;
             case 'f':
             case 'F':
                return 15;
             default:
                return -1;
          }
       }  // end hexValue()

    }  // end class

[ Exercises | Chapter Index | Main Index ]