
Список литературы
Stutz, Michael Get started with GAWK: AWK language fundamentals.developerWorks. IBM(September 19, 2006). — «[AWK] часто называют языком, управляемым данными -- операторы программы описывают подходящие входные данные и их обработку, а не последовательность шагов программы»Архивированоиз первоисточника 2 сентября 2012. Проверено 23 октября 2010.
(1989) «Object-oriented design: a responsibility-driven approach». Conference Proceedings on Object-Oriented Programming Systems, Languages and Applications (ACM): 71–75.DOI:10.1145/74877.74885.
http://ru.wikipedia.org/wiki/Сжатие_данных
http://ru.wikipedia.org/wiki/Алгоритм_Лемпеля_-_Зива_-_Велча
http://ru.wikipedia.org/wiki/Событийно_ориентированное_программирование
http://ru.wikipedia.org/wiki/Программирование_потоком_данных
Блок-схема Листинг программы
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/************************************************************************
** Демонстрационная программа для LZW-алгоритма сжатия/распаковки данных.
** Mark R. Nelson
*************************************************************************/
#include <stdio.h>
#define BITS 12 /* Установка длины кода равной 12, 13 */
#define HASHING_SHIFT BITS-8 /* или 14 битам. */
#define MAX_VALUE (1 << BITS) - 1/* Отметим, что на MS-DOS-машине при */
#define MAX_CODE MAX_VALUE - 1 /* длине кода 14 бит необходимо компи- */
/* лировать, используя large-модель. */
#if BITS == 14
#define TABLE_SIZE 18041 /* Размер таблицы строк должен быть */
#endif /* простым числом, несколько большим, */
#if BITS == 13 /* чем 2**BITS. */
#define TABLE_SIZE 9029
#endif
#if BITS <= 12
#define TABLE_SIZE 5021
#endif
enum STATES {
NAME, SIZE, DATA
};
typedef struct {
char ** frames;
Int n_files;
int i; // current file index
FILE *f; // current file
char buf[1024];
int buf_pos;
int buf_len;
} InArchStream;
typedef struct {
int state; // статус (1,2,3) (1- читаю имя файла, 2 читаю инфу о длине(4 байта), 3 читаю само тело файла)
char fname [1050]; //
int fname_pos; // позиция на имени
int flen; // длина файла походу(4 байта которые.)
FILE * out; // сам файл
int flen_count; // счетчик по длине файла(от 0 байта до 4 байта)
int out_count; //
} OutArchStream;
struct context
{
/* Это массив для значений кодов */
int *code_value; //izbavlyaemsya ot globalnih peremennyh.
/* Этот массив содержит префиксы кодов */
unsigned int *prefix_code;
/* Этот массив содержит добавочные символы */
unsigned char *append_character;
/* Этот массив содержит декодируемые строки */
unsigned char decode_stack[4000];
};
/*
** Следующие две процедуры управляют вводом/выводом кодов
** переменной длины. Они для ясности написаны чрезвычайно
** простыми и не очень эффективны.
*/
int input_code(FILE *input)
{
unsigned int return_value;
static int input_bit_count=0;
static unsigned long input_bit_buffer=0L;
while (input_bit_count <= 24)
{
input_bit_buffer|=(unsigned long)getc(input)<<(24-input_bit_count);
input_bit_count += 8;
}
return_value=input_bit_buffer >> (32-BITS);
input_bit_buffer <<= BITS;
input_bit_count -= BITS;
return(return_value);
}
int output_code(FILE *output,unsigned int code)
{
static int output_bit_count=0;
static unsigned long output_bit_buffer=0L;
output_bit_buffer|=(unsigned long)code<<(32-BITS-output_bit_count);
output_bit_count += BITS;
while (output_bit_count >= 8)
{
putc(output_bit_buffer >> 24,output);
output_bit_buffer <<= 8;
output_bit_count -= 8;
}
}
int arch_get_c(InArchStream * stream){
while (1) {
int a;
if (stream->buf_pos<stream->buf_len){
a=(unsigned char)stream->buf[stream->buf_pos];
stream->buf_pos++;
return a;
}
if (stream->f==NULL){
if (stream->i==stream->n_files)
return -1;
stream->f=fopen(stream->frames[stream->i], "rb");
if(stream->f==NULL)
return -1;
strcpy(stream->buf,stream->frames[stream->i]);
fseek(stream->f, 0, SEEK_END);
int size = ftell(stream->f);
fseek(stream->f, 0, SEEK_SET);
int fname_len=strlen(stream->buf);
*(int *)&stream->buf[fname_len+1] = size;
stream->buf_len=fname_len+5;
stream->buf_pos=0;
continue;
}
int n =fread(stream->buf,1,sizeof(stream->buf),stream->f);
stream->buf_pos=0;
stream->buf_len=n;
if (stream->buf_len == 0) {
fclose(stream->f);
stream->f=NULL;
stream->i++;
}
}
}
int arch_put_c(char c, OutArchStream * stream) {
char * bytes;
switch (stream->state) {
case NAME:
stream->fname[stream->fname_pos++] = c;
if (c == 0) {
stream->state = SIZE;
stream->out_count = 0;
}
break;
case SIZE:
bytes = (char *)(&stream->flen);
bytes[stream->out_count++] = c;
if (stream->out_count == 4) {
stream->state = DATA;
stream->out = NULL;
}
break;
case DATA:
if (stream->out == NULL) {
stream->out = fopen(stream->fname, "wb");
stream->flen_count = 0;
}
putc(c, stream->out);
stream->flen_count ++;
if (stream->flen_count == stream->flen) {
fclose(stream->out);
stream->state = NAME;
}
break;
}
}
/*
** Процедура хэширования. Она пытается найти сопоставление для строки
** префикс+символ в таблице строк. Если найдено, возвращается индекс.
** Если нет, то возвращается первый доступный индекс.
*/
int find_match(int hash_prefix,unsigned int hash_character,struct context *ctx){
int index;
int offset;
index = (hash_character << HASHING_SHIFT) ^ hash_prefix;
if (index == 0)
offset = 1;
else
offset = TABLE_SIZE - index;
while (1)
{
if (ctx->code_value[index] == -1)
return(index);
if (ctx->prefix_code[index]==hash_prefix&&ctx->append_character[index]==hash_character)
return(index);
index -= offset;
if (index < 0)
index += TABLE_SIZE;
}
}// end of find_math;
/*
** Процедура сжатия.
*/
int compress(InArchStream *input, FILE *output, struct context *ctx){
unsigned int next_code;
unsigned int character;
unsigned int string_code;
unsigned int index;
int i;
next_code=256; /* Next_code - следующий доступный код строки */
for (i=0;i<TABLE_SIZE;i++)/*Очистка таблицы строк перед стартом */
ctx->code_value[i]=-1;
i=0;
printf("Compressing...\n");
string_code=arch_get_c(input); /* Get the first code*/
/*
** Основной цикл. Он выполняется до тех пор, пока возможно чтение
** входного потока. Отметим, что он прекращает заполнение таблицы
** строк после того, как все возможные коды были использованы.
*/
while ((character=arch_get_c(input)) != (unsigned)EOF)
{
if (++i==1000) /* Печатает * через каждые 1000 */
{ /* чтений входных символов (для */
i=0; /* умиротворения зрителя). */
printf("*");
}
/* Смотрит, есть ли строка */
index=find_match(string_code,character,ctx);
if (ctx->code_value[index] != -1) /* в таблице. Если есть,*/
string_code=ctx->code_value[index];/* получает значение кода*/
else /* Если нет, добавляет ее*/
{ /* в таблицу. */
if (next_code <= MAX_CODE)
{
ctx->code_value[index]=next_code++;
ctx->prefix_code[index]=string_code;
ctx->append_character[index]=character;
}
output_code(output,string_code);/*Когда обнаруживается, что*/
string_code=character; /*строки нет в таблице, */
} /*выводится последняя строка*/
} /*перед добавлением новой */
/*
** End of the main loop.
*/
output_code(output,string_code); /* Вывод последнего кода */
output_code(output,MAX_VALUE); /* Вывод признака конца потока */
output_code(output,0); /* Очистка буфера вывода */
printf("\n");
} //end of compress();
/*
** Процедура распаковки. Она читает файл LZW-формата и распаковывает
** его в выходной файл.
*/