программа для сжатия файла в код длины прогона на C

Я пишу программу для сжатия файла, состоящего из шестнадцатеричных значений, в код длины прогона. Например, для файла:

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

мой код должен создать следующий файл:

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

Я не знаю, почему программа, которую я написал, зависает. Любая помощь будет оценена по достоинству.

#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.");
    }
}

РЕДАКТИРОВАТЬ: я обновил код, удалив аргумент! Feof (file) и заменив его фактической функцией ввода-вывода. Спасибо за понимание. Однако моя программа по-прежнему не работает.


person Jane Catherine Yoon    schedule 04.12.2016    source источник
comment
Как можно считать больший результат сжатием?   -  person Weather Vane    schedule 04.12.2016
comment
а (! feof (fp)) всегда неверно   -  person user3386109    schedule 04.12.2016
comment
В большинстве случаев это не лучший метод сжатия; он работает хорошо только в том случае, если есть повторяющиеся длинные части ввода. Если нет повторений, размер файла фактически увеличивается вдвое. Если ввод: 6f 6f 6f 6f 6f 6f 01 01 01 01, на выходе будет 06 6f 04 01, что уменьшает размер файла до 40% от его первоначального размера. Его эффективность зависит от ввода.   -  person Jane Catherine Yoon    schedule 04.12.2016
comment
Вы имеете в виду, что! feof (file) всегда принимает значение false?   -  person Jane Catherine Yoon    schedule 04.12.2016
comment
Функции ввода-вывода возвращают значение, позволяющее определить, отказал он или нет. Когда он выходит из строя, вы используете feof(file), чтобы определить, произошел ли сбой из-за конца файла или из-за ошибки. Щелкните вопрос, связанный с пользователем 3386109 выше, чтобы узнать об этом подробнее.   -  person    schedule 04.12.2016
comment
Вы также выполняете while (flag==TRUE) и используете fscanf() внутри этого цикла без проверки возвращаемого значения fscanf(), поэтому, если вы встретите конец файла, он будет зацикливаться на fscanf() и выполнить count = count + 1 без установки flag на FALSE.   -  person    schedule 04.12.2016
comment
Пожалуйста, не исправляйте опубликованный код, если это не ваш реальный код.   -  person Weather Vane    schedule 04.12.2016


Ответы (1)


Я не знаю, почему ваша программа "зависает", но это может сработать лучше. Заметьте, я выбросил бессмысленные a, b, c и правду.

#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 

Лучший способ реализовать RLE - выбрать значение «escape», чтобы определить, когда следует сжатие. Таким образом, 3 значения будут кодировать последовательность сжатия, поэтому стоит сжимать только 3 или более одинаковых. Все остальные символы дословны, кроме самого escape-символа.

person Weather Vane    schedule 04.12.2016