Previous | Table of Contents | Next

In MAIN-C.C, a compression module supplies three things: a Usage string, which can print out a list of parameters, etc.; a CompressionName string, which lets the MAIN-C.C program print out the compression method; and a CompressFile() routine, which actually compresses the file. In this chapter, these routines are in a file called HUFF.C, which implements an order 0 model with a Huffman coder. MAIN-C.C is shown below.

    /*********************** Start of MAIN-C.C **********************/
    /*
    * This is the driver program used when testing compression algorithms.
    * In order to cut back on repetitive code, this version of main is
    * used with all of the compression routines.  In order to turn it into
    * a real program, it needs to have another module that supplies one
    * routine and two strings, namely:
    *
    *    void CompressFile( FILE *input, BIT_FILE *output,
    *                        int argc, char *argv );
    *    char *Usage;
    *    char *CompressionName;
    *
    * The main() routine supplied here has the job of checking for valid
    * input and output files, opening them, and then calling the
    * compression routine.  If the files are not present, or no arguments
    * are supplied, it prints out an error message, which includes the
    * Usage string supplied by the compression module.  All of the
    * routines and strings needed by this routine are defined in the
    * main.h header file.
    *
    * After this is built into a compression program of any sort, the
    * program can be called like this:
    *
    *    main-c infile outfile [ options ]
    *
    */
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include "bitio.h"
    #include "errhand.h"
    #include "main.h"
    #ifdef ___STDC___

    void usage_exit( char *prog_name );
    void print_ratios( char *input, char *output );
    long file_size( char *name );

    #else

    void usage_exit();
    void print_ratios();
    long file_size();

    #endif

    int main( argc, argv )
    int argc;
    char *argv[];
    {
         BIT_FILE *ouput;
         FILE *input;

         setbuf( stdout, NULL );
         if ( argc < 3 )
              usage_exit( argv[ 0 ] );
         input = fopen(argv [ 1 ], "rb" );
         if ( input == NULL )
              fatal_error( "Error opening %s for input/n", argv[ 1 ] );
         output = OpenOutputBitFile( argv[ 2 ] );
         if ( output == NULL )
              fatal error( "Error opening %s for input/n", argv[ 2 ] );
         printf( "\nCompressing %s to %s\n", argv[ 1 ], argv[ 2 ] );
         printf( "Using %s\n, CompressionName );
         argc -= 3;
         argv += 3;
         CompressFile( input, output, argc, argv );
         CloseOutputBitFile( output );
         fclose( input );
         print_ratios( argv[ 1 ], argv[ 2 ] );
         return( 0 );
    }

    /*
    * This routine just wants to print out the usage message that is
    * called for when the program is run with no parameters.  The first
    * part of the Usage statement is supposed to be just the program
    * name. argv[ 0 ] generally holds the fully qualified path name
    * of the program being run.  I make a half-hearted attempt to strip
    * out that path info and file extension before printing it.  It should
    * get the general idea across.
    */
    void usage_exit( prog_name )
    char *prog_name;
    {
         char *short_name;
         char *extension;

         short_name = strrchr( prog_name, '\\' );
         if (short_name == NULL )
              short_name = strrchr( prog_name, '/' );
         if (short_name == NULL )
              short_name = strrchr( prog_name, ':' );
         if (short_name != NULL )
              short_name++;
         else
              short_name = prog_name;
         extension = strrchr( short_name, '.' );
         if ( extension != NULL )
              *extension = '\0';
         printf( "\nUsage: %s %s\n", short_name, Usage );
         exit( 0 );
    }

    /*
    * This routine is used by main to get the size of a file after it has
    * been closed.  It does all the work, and returns a long.  The main
    * program gets the file size for the plain text, and the size of the
    * compressed file, and prints the ratio.
    */
    #ifndef SEEK_END
    #define SEEK_END 2
    #endif

    long file_size( name )
    char *name;
    {
         long eof ftell;
         FILE *file;

         file = fopen( name, "r");
         if ( file == NULL )
              return( OL );
         fseek( file, OL, SEEK_END );
         eof_ftell = ftell( file );
         fclose( file );
         return( eof_ftell );
    }

    /*
    * This routine prints out the compression ratios after the input and
    * output files have been closed.
    */
    void print_ratios( input, output )
    char *input;
    char *output;
    {
         long input_size;
         long output_size;
         int ratio;
         input_size = file_size( input );
         if ( input_size == 0 )
             input_size = 1;
         output_size = file_size * 100L / input_size );
         ratio = 100 - (int) ( output_size * 100L / input_size );
         printf( "\nInput bytes:        %ld\n", input_size );
         printf( "Output bytes:      %ld/n", output_size );
         if ( output_size == 0 )
             output_size = 1;
         printf( "Compression ratio:  %d%%\n", ratio );

    /*********************** End of MAIN-C.C *************************/

Previous | Table of Contents | Next