Помощь - Поиск - Пользователи - Календарь
Полная версия: Сжатие и распаковка файлов
Форум «Всё о Паскале» > Современный Паскаль и другие языки > Ада и другие языки
18192123
Требуется разработать программу для сжатия и распаковки файлов. Для кодирования используется алгоритм Шеннона-Фано. Собственно, проблем с кодированием нет. Вопрос у меня относительно сжатия. Как от меня требуется, сообщение из исходного(входного файла) файла я должна записать в выходной файл (он по заданию двоичный), предварительно закодировав. Для сжатия требуется побайтовый вывод в файл..т.е. у нас есть схема кодирования..считываем очерёдный символ из входного сообщения..ищем для него код...нашли - готовы записывать..но здесь побайтовый вывод. Мы должны сначала набрать 8 бит ,и только потом выводить (но вот код найденный может занимать меньше 8 бит..может больше - у меня с предусмотрением этого проблема)

typedef struct structure {unsigned char id; int count; char code[10];} STRUCTURE;

id - поле для символа
count - число вхождений символа
code[10] - сам код

mas - массив структур

перед выводом в выходной файл массив структур упорядочен по убыванию (убыванию поля count)
как вспомогательный используется массив char mas_code[255][10] (массив содержит в нулевом столбце количество вхождений символа, в остальных коды из 0 и 1)

а вот что делать с этим самым побайтовым выводом - не получается.....

как бы попытки есть...но записывается несовсем правильно не совсем правильно...


int get_byte(char mas_code[255][10],STRUCTURE *mas)
{ unsigned char mask;
mask=0x00;
FILE *f, *g;
char str[60];
int pos_m=8; // pos_m - свободные места в маске
int pos_c, st=0; // pos_c - очерёдное место в коде некоторого символа
f=fopen("1.txt", "r+t");
g=fopen("2.txt", "w");
char x;
while(!feof(f))
{ if (pos_m) { x=fgetc(f);
st=0;
while ( mas[st].id!=x)
st++;
pos_c=1;
while ((pos_m)&&(pos_c<=mas_code[st][0]))
{ mask=mask<<1;
mask|=mas_code[st][pos_c];
pos_m--;
pos_c++;

}
}
else {fprintf(g,"%0x", mask);
itoa(mask,str,2);
printf("%s", str);
printf(" ");
mask=0x00;
pos_m=8;
if (pos_c<=mas_code[st][0])
{ while ((pos_m)&&(pos_c<=mas_code[st][0]))
{ mask<<1;
mask=mask|mas_code[st][pos_c];
pos_m--;
pos_c++;

}



}

}
}
fclose(f);
fclose(g);
return 8-pos_m; // возвращаем кол-во бит, задействованных в последнем байте - нужно по заданию
}


18192123
Я конечно пониманию, что никому не хочется разбираться в чужом коде, но хоть посоветуйте, как можно осуществить побайтовый вывод в файл???
Malice
Цитата(18192123 @ 7.12.2007 14:09) *

Я конечно пониманию, что никому не хочется разбираться в чужом коде, но хоть посоветуйте, как можно осуществить побайтовый вывод в файл???

Копить надо результат где-то и записывать первые накопившиеся 8 бит, затем их отрезать.
Копить можно в строкой переменной, но понадобятся функции перевода Bin2Dec, dec2Bin. Или использовать для храниния числовую переменнную разрядностью 16 (можно и больше) бит + хранить колво значимых бит в этом числе. В этом случае придется оперировать битовыим операциями - сдвиги, сложения и т.п.)
Второй вариант использовался вот здесь:
Программа архиватор- разархиватор текстовых файлов
Там задача похожая, запись по несколько бит.
volvo
Цитата
хоть посоветуйте, как можно осуществить побайтовый вывод в файл???
Вот имитация побайтного вывода закодированной информации. Теория взята здесь: Сайт

Данная программа отработает правильно только если коды символов имеют длину, не превышающую 7. Для других случаев могут быть проблемы, я не проверял на других данных...
#include <stdlib.h>
#include <stdio.h>

typedef struct _codes {
char ch;
unsigned char code;
int codelen;
} codes;

codes table[5] = {
{'d', 0, 2},
{'c', 1, 2},
{' ', 2, 2},
{'b', 6, 3},
{'a', 7, 3}
};

int main() {
unsigned char buffer, T;
int i, len = 0;
char string[16];

char *p, *s = "aaa bbb cccc ddddd\0";

p = s;
buffer = 0;
while(*p) {
for(i = 0; i < 5; i++) {
if(*p == table[i].ch) break;
}

len += table[i].codelen;
if(len > 8) {
buffer = buffer << (8 - (len - table[i].codelen));
T = ((table[i].code >> (len - 8)));
buffer |= T;
printf("%08s\n", itoa(buffer, string, 2));

len -= 8;
buffer = 0;
buffer = (table[i].code << (8 - len));
buffer >>= (8 - len);
}
else {
buffer = (buffer << table[i].codelen) | table[i].code;
}

p++;
}
return 0;
}

(не забывай о том, что после окончания работы программы в buffer-е может остаться не выведенная информация)
18192123
В соответствии с заданием нужно чтоб программа запускалась с командной строки...с 3-мя параметрами (имя входного файла, выходного файла и режим работы - кодирование или декодирование). В главной программе тогда две основных процедуры - кодирования и декодирования, которые будут вызываться в соответствии с параметром из командной строки, означающим режим работы....я знаю, что в void main передаются два стандартных параметра, как раз для работы с командной строкой....но как соотвести это - не знаю..объясните пожалуста, как делать...
18192123
как просто запустить программу с командной строки - это ясно..а вот как задать там параметры и передать в программу - мне не понятно....
volvo
Запускать программу с параметрами:
Start -> Run -> "G:\Vlady Documents\Programs\CBlock\console_c\console.exe" text.txt text2.txt code
(замени на свои данные. Все, что НЕ в кавычках - это параметры)

В программе должны анализироваться параметры командной строки... Что-то типа:
int main(int argc, char *argv[]) {

if(argc < 3) { /* Проверяем количество параметров */
printf("Usage: prog.exe infile outfile code/decode\n");
return 1;
}
char infile[128], outfile[128];
strcpy(infile, argv[1]); /* Первый - имя входного файла */
strcpy(outfile, argv[2]); /* Второй - имя выходного файла */

/* Ну, а третий - если не "code", значит ДЕкодирование */

/* В зависимости от третьего параметра вызываешь либо одну процедуру либо другую */
if(!strcmp(argv[3], "code")) {
printf("coding from '%s' to '%s'\n", infile, outfile);
}
else {
printf("decoding from '%s' to '%s'\n", infile, outfile);
}
getch();
}
18192123
Цитата(volvo @ 13.12.2007 23:06) *

Запускать программу с параметрами:
Start -> Run -> "G:\Vlady Documents\Programs\CBlock\console_c\console.exe" text.txt text2.txt code


большое спасибо! теперь всё ясно!
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.