> ### Solution for
> Programming Exercise 4.2

> 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 ]