CS-211 Lab 7 -- Using Arrays

Last week started studying arrays. This lab is designed to some practical experience using arrays. In order to do so, we will create a simple C program that takes a single integer as an argument, and prints out the hexadecimal (base 16) representation of that argument.

The most important concept in this lab is the difference between a mathematical value, and the character symbol used to represent that value. For instance, the value 0 is represented by the character '0'. If you look at an ASCII table, the number that maps to the character '0' is 48. The trick to translating a single hexadecimal value to the character that represents that value is to make an array of characters, where the index is the numeric value, and the element of the array at that index is the symbol used to represent that value. Here is what that table looks like:

Index0123456789101112131415
Element'0''1''2''3''4''5''6''7''8''9''A''B''C''D''E''F'

With this table in place, if we know the value of a hex digit, we can look up the symbol for that digit in the table just by using the value as an index into the table.

The largest an integer can be in C is 32 bits wide. (On some machines, integers are only 16 bits wide, but if we allow for up to 32 bits, we'll be OK.) Each hexadecimal digit represents a number between 0 and 15, which corresponds to four bits. Therefore, we can express a 32 bit number using 8 hexadecimal digits. We will need to create a function that translates an integer into an array of 8 hexadecimal digits.

Your program to translate integers into hexadecimal value should support input of both positive and negative integers, but converting negative numbers to hex is confusing. If you copy a signed integer to an unsigned integer, that doesn't change the bits themselves... just how you interpret them. Since the bits are the same, the hexadecimal value will be the same. If we copy the signed integer input value to an unsigned integer variable, and translate that to hexadecimal, we will still get the right answer and we don't have to deal with negative numbers.

There is one other trick for this lab. To get the value for the rightmost hex digit, all you need to do is find the remainder of the number when dividing by 16. You can then look up the symbol for this value in the table. Then, if you do integer division by 16, that will throw away the remainder, and move the rest of the number over (to the right by four bits). If you find the remainder of this result when dividing by 16, that will be the value of the second hexadecimal digit from the right. You can repeat this process 8 times to get all 8 hexadecimal digits.

Getting Started

Make a lab07 directory, and create a file in that directory called toHex.c. In your toHex.c file will need to include stdio.h and stdlib.h, and you will need the standard main function. Your main function should invoke the atoi standard library function on the first command line argument, as we have done in previous labs. If you get more or less than a single command line argument (other than the command itself), you should print an error message and quit.

Assuming you saved the result of the atoi function in an integer variable called n, then your main function should invoke the following printf statement:

 printf("The number %d is %s in hex\n",n,toHex(n)); 

Note: An alternative solution to this problem is to use the built-in functionality of printf. For the purposes of this lab, if you do so, you won't learn anything about arrays, so this solution is not allowed. But if you want to check your work, the following statement will produce the exact same results as the tohex function if you coded tohex correctly:

  printf("The number %d is %08X in hex\n",n,n);

If you use this statement, make sure you comment it out before submitting your code. This is not a valid solution to this lab.

Creating the toHex function

Obviously, for this to work, you will need a function called toHex(unsigned int n), which will return a string. There are two tricks to returning a string. First, the return type must be char * (which is a pointer to an array of characters). Therefore, the declaration of the toHex function should look like:

  char * toHex(unsigned int n);

The second problem is that if we use a normal automatic C variable to save the result of the conversion, then it will get deleted when the toHex function ends. The problem is that we want to use this array AFTER the toHex function ends. There are several ways to solve this problem, but one of the easiest ways is to create a static variable in the toHex function to hold the result. Since strings consist of arrays of characters followed by a null terminator, in order to declare a variable for our result, we can use the following declaration:

  static char hexNumber[9] = { 0x00 };

This will create a static variable that lasts the whole life of our program with 9 elements, all initialized to the null character, 0x00. This looks like the following

hexNumber
Index012345678
Element0x000x000x000x000x000x000x000x000x00

Similarly, we can create an array that maps values to symbols, as described above using the syntax:

  char digits[16]={ '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};

In the hexNumber table, the RIGHTMOST position is hexNumber[7], leaving room in hexNumber[8] for the trailing null character, 0x00. You can get the value of the rightmost digit by n%16. This value is then the index into the digits array, which has single character elements. Then, if you do n=n/16;, then the new value of n will have the second rightmost digit. I used a for loop that goes backwards from 7 to 0 to fill in digits 7, 6, 5 , ... 2, 1, 0 of the hexNumber array.

Once you have filled in the hexNumber array, then all you need to do is:

  return hexNumber;

This will return the string hexNumber. The main function must use the returned value before toHex is called again, because tohex will write a new value into the space reserved for the hexNumber string. In the general case, that might be a problem, but since we are only calling toHex once from the main function, we don't need to worry about that.

Testing your Program

Once your toHex.c code is written, compile it and make sure there are no error or warning messages. Once the compile is complete, test your code. For instance, here are some basic results...

CommandResult
./toHex 0The number 0 is 00000000 in hex
./toHex 4The number 4 is 00000004 in hex
./toHex 12The number 12 is 0000000C in hex
./toHex -1The number -1 is FFFFFFFF in hex
./toHex -456The number -456 is FFFFFE38 in hex

Extra Credit

There is a bit-twiddling way to implement the toHex function. To get the value of the rightmost 4 bits, all we have to do is and n with the value 0x0000000F. This takes the place of the much slower remainder function. Then, to shift the rightmost 4 bits out, and the next 4 bits in, all we have to do is n>>4. This takes the place of (and is much more efficient than) integer division. For extra credit, implement toHex with this bit-twiddling implementation.

Go to MyCourses, and open the CS-211 page, and choose the "Content" hyperlink on the left list of options. You will see a "Lab 07 Submission" icon to upload your toHex.c file. Make this submission before the due date of Friday, October 27, at 11:59 PM. You may submit as many times as you want before the due date, but only the latest submission will be graded.

Lab Grading

This lab is worth 10 points. You will get deductions as follows: