Encoding and Decoding, Part VI

Data encoded by my hexencode system is formatted. That means that the decoding program must look for both the header and footer in that formatted output. In last week’s Lesson, code was added to confirm the input file’s first line as the header. This week’s modification is to search for the end of encoded text.

The code is getting rather long, but the main modification from last week is the addition of the process_line() function. Here’s the code:

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

#define LINE_LENGTH 73
#define TRUE 1
#define FALSE 0

void check_file(char *line);
int process_line(char *line);

int main()
{
    char line_buffer[LINE_LENGTH];
    char c;
    int buffer_index = 0;
    int first_line = TRUE;

    while(1)
    {
        c = getchar();
        if( c == EOF)
            break;
        line_buffer[buffer_index] = c;
        buffer_index++;
        if( buffer_index > LINE_LENGTH)
        {
            /* overflow condition */
            puts("\nInvalid hexcode line format");
            return(1);
        }
        if( c == '\n')
        {
            /* terminate string */
            line_buffer[buffer_index] = '\0';
            /* process first line separately */
            if(first_line)
            {
                check_file(line_buffer);
                first_line = FALSE;
            }
            else
            {
                if(process_line(line_buffer))
                    break;
            }
            /* reset index */
            buffer_index = 0;
        }
    }

    return(0);
}

void check_file(char *line)
{
    if( strncmp(line,"START HEX CODE",14) == 0 )
    {
        /* check version number here */
        /* offset 17 bytes */
        return;
    }
    else
    {
        puts("Improper hexcode file format");
        exit(1);
    }
}

int process_line(char *line)
{
    if( strncmp(line,"END HEX CODE",12) == 0 )
    {
        return(TRUE);
    }
    else
    {
        /* process the input here */
        printf("%s",line);
        return(FALSE);
    }
}

Rather than use a printf() statement at Line 42 (in last week’s code), the else part of the decision now calls the process_line() function (Line 44). That function returns TRUE or FALSE, so it’s placed inside an if test. When the result is TRUE, meaning the last line in the encoded file is processed, then the loop breaks (Line 45). The decoding is finished.

The process_line() function is prototyped at Line 9 and defined at Line 70. For now, it contains an strncmp() function to scan for the final line of the encoded file (Line 71). If found, the function returns TRUE to break the main program’s while loop. Otherwise, input is processed, which at this point the text is displayed at Line 79 and the value FALSE is returned (Line 80).

Why are you taking so long to do this?

Glad you asked: I want to ensure that all the program’s pieces work, one at a time. If you code too much at once, you deal with multiple errors and problems. Solve the puzzle one step at a time and the process runs faster.

The sample output displays the hexadecimal digits from the input file. Here how it looks when run on the gettysburg.hexc input file:

blog$ ./a.out < gettysburg.hexc 
 EC C5 DF D8 8A D9 C9 C5 D8 CF 8A CB C4 CE 8A D9 CF DC CF C4 8A D3 CF CB
 D8 D9 8A CB CD C5 8A C5 DF D8 8A CC CB DE C2 CF D8 D9 8A C8 D8 C5 DF CD
 C2 DE 8A CC C5 D8 DE C2 8A C5 C4 8A DE C2 C3 D9 8A C9 C5 C4 DE C3 C4 CF
 C4 DE 8A CB 8A C4 CF DD 8A C4 CB DE C3 C5 C4 86 8A C9 C5 C4 C9 CF C3 DC
 CF CE 8A C3 C4 8A C6 C3 C8 CF D8 DE D3 86 8A CB C4 CE 8A CE CF CE C3 C9
 CB DE CF CE 8A DE C5 8A DE C2 CF 8A DA D8 C5 DA C5 D9 C3 DE C3 C5 C4 8A
 DE C2 CB DE 8A CB C6 C6 8A C7 CF C4 8A CB D8 CF 8A C9 D8 CF CB DE CF CE
 8A CF DB DF CB C6 84 A0 A0

For next week's Lesson, I (finally) finish the decoding program by adding the process that translates the hexadecimal bytes back into values, performs the XOR 0xAA operation, and outputs the original input.

Leave a Reply