Encoding and Decoding, Part III

You can output values in the hexadecimal format, thanks to the %x and %X placeholders in the printf() function. Getting hex strings as input is also possible, but not entirely obvious.

To continue from last week’s Lesson, the encoded file outputs bytes as hexadecimal values, which appear as strings. To decode that encoded information, the hexadecimal strings must be converted to their decimal values.

The good news is that the scanf() function borrows the %x and %X placeholders from printf(). So it’s possible to read a hexadecimal string and convert it into a value, as the following code demonstrates:

#include <stdio.h>

int main()
{
    int d;

    printf("Type a hex value: ");
    scanf("%2x",&d);
    printf("0x%2x is %d decimal.\n",d,d);

    return(0);
}

The scanf() function at Line 8 reads the first two digits of input and converts them to a hexadecimal value, stored in variable d. The value is output in Line 9.

Here’s a sample run:

Type a hex value: AA
0xaa is 170 decimal.

The difference between %x and %X is whether the output is lowercase or uppercase, but for input it apparently doesn’t matter (at least not on my compiler).

You can also decode hexadecimal manually. Yes, you’re reinventing the wheel, but this solution is more flexible than using scanf().

In the following code, input is saved as a two-byte string, hex. Each character is then extrapolated as a hexadecimal digit, the first digit is adjusted, and the final value displayed.

#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>

int hex2int(char *hex);
int char2int(char h);

int main()
{
    int v;
    char hex[3];

    hex[0] = (char)fgetc(stdin);
    hex[1] = (char)fgetc(stdin);
    hex[2] = '\0';  /* create string */
    v = hex2int(hex);
    printf("0x%s = %d\n",hex,v);

    return(0);
}

int hex2int(char *hex)
{
    int a,b;

    a = char2int(*(hex+0)); /* first character */
    b = char2int(*(hex+1)); /* second char */

    return( (a << 4) + b);
}

int char2int(char h)
{
    if( isnumber(h) )
        return( h - '0');
    h = toupper(h);
    if( h >= 'A' && h <= 'F' )
        return( h - 'A' + 0x0A);
    /* invalid character */
    {   
        printf("\nInvalid hex character: %c\n",h);
        exit(1);
    }   

    return(0);
}

Two bytes are read and stored into the string hex at Lines 13 and 14. The hex2int() function converts the value at Line 15.

At Line 22, the hex2int() function accepts a two-character string as an argument. Each character in the string is converted to a value, at Lines 26 and 27. The values are manipulated so that value a (the first digit in the number) is multiplied by 16; it’s shifted left four digits. The second value is added to the first, which creates and returns the hexadecimal byte value.

At Line 32, individual hex characters are converted to values. The isnumber() function at Line 33 works to return characters 0 through 9 as a value. A similar calculation is made on letters in Line 38. When the letter falls outside the range A to F, the else condition displays an error message and the program terminates.

Here’s a sample run:

AA
0xAA = 170

Above, I typed AA at the prompt and then pressed the Enter key. The program evaluated 0xAA and returned the proper decimal representation, 170.

Now that the hex conversion issue is solved, then next step is to begin writing the decoding program. That process begins in next week’s Lesson.

Leave a Reply