0

I am writing a program to compress a file consisting of hexadecimal values into run-length code. For example, given a file:

46 6f 6f 20 62 61 72 21 21 21 20 20 20 20 20

my code should produce the following file:

01 46 02 6f 01 20 01 62 01 61 01 72 03 21 05 20

I don't know why the program I've written gets stuck. Any help would be appreciated.

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

#define TRUE 1
#define FALSE 0

int main(void){
    int a, b, c, count=1, flag=TRUE;

    FILE *file;
    FILE *out;

    file = fopen("input.txt", "r");

    if(file){
        out = fopen("input.txt.out", "a");
        fscanf(file, "%x", &a);
        while(fscanf(file, "%x", &c)){
            while(flag==TRUE){
                if(c==a){
                    count= count+1;
                }else{
                    flag = FALSE;
                }
                b=a;
                a=c;
            }
            fprintf(out, "%d %02x ", count, b);
            count = 1;
            flag = TRUE;
        }
    }else{
        printf("ERROR: file not found.");
    }
}

EDIT: I updated the code removing the !feof(file) argument and replacing it with an actual I/O function instead. Thanks for the insight. However, my program still doesn't work.

  • 1
    How can a larger output be considered to be "compression"? – Weather Vane Dec 04 '16 at 19:07
  • 1
    [while(!feof(fp)) is always wrong](https://stackoverflow.com/questions/5431941) – user3386109 Dec 04 '16 at 19:08
  • 1
    It is not a great method of compression in most cases; it only works well if there are long parts of the input that are repeating. If there is no repetition the file actually doubles in size. If the input is: 6f 6f 6f 6f 6f 6f 01 01 01 01 the output is 06 6f 04 01 which reduces the file to 40% of its orginal size. It's effectiveness depends on the input. – Jane Catherine Yoon Dec 04 '16 at 19:14
  • do you mean that !feof(file) alway evaluates to false? – Jane Catherine Yoon Dec 04 '16 at 19:18
  • I/O functions return a value that allows you to determine whether it failed or not. When it fails, that's when you use `feof(file)` to determine whether it failed due to end-of-file or due to an error. Click the question that user3386109 linked above to read more about it. –  Dec 04 '16 at 19:21
  • 1
    You're also doing `while (flag==TRUE)` and using `fscanf()` inside that loop without checking the return value of `fscanf()`, so if you encounter the end of the file, it'll loop on the `fscanf()` and do `count = count + 1` without ever setting `flag` to `FALSE`. –  Dec 04 '16 at 19:24
  • Please don't correct posted code unless it was not your actual code. – Weather Vane Dec 04 '16 at 19:29

1 Answers1

1

I don't know why your program "gets stuck" but this might work better. Note I have dumped the meaningless a, b, c and the truth stuff.

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

int main(void){
    int lastchar, thischar, count;

    FILE *finp;
    FILE *fout;
    finp = fopen("input.txt", "r");
    fout = fopen("output.txt", "w");                // changed "a" to "w"
    if(fout == NULL || finp == NULL) {
        puts("Error opening file(s)");
        exit(1);
    }

    count = 1;
    fscanf(finp, "%x", &lastchar);

    while(fscanf(finp, "%x", &thischar) == 1) {     // func value better then feof
        if(thischar == lastchar) {
            count++;
        }
        else {
            fprintf(fout, "%02X %02X ", count, lastchar);
            count = 1;
        }
        lastchar = thischar;
    }
    fprintf(fout, "%02X %02X ", count, lastchar);   // discharge remaining

    fclose(fout);
    fclose(finp);
    return 0;
}
Program input:  46 6f 6f 20 62 61 72 21 21 21 20 20 20 20 20

Program output: 01 46 02 6F 01 20 01 62 01 61 01 72 03 21 05 20 

A better way of implementing RLE is to choose an "escape" value to define when a compression follows. Thus 3 values will encode a compression sequence, and so it is only worth compressing 3 or more the same. All other characters are verbatim, except the escape character itself.

Weather Vane
  • 33,872
  • 7
  • 36
  • 56